package mspbots.next.ticket.core.grader.interceptor;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonNode;
import lombok.Data;
import lombok.extern.log4j.Log4j2;
import mspbots.next.ticket.core.grader.AbstractGradeRuleAdapter;
import mspbots.next.ticket.core.grader.GradeRuleInterceptorRegistration;
import mspbots.next.ticket.core.points.PointResult;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;
import reactor.core.publisher.Mono;

import java.util.List;
import java.util.Map;

/**
 * @author Harry hou
 * @date 2019/11/18 10:26
 */
@Log4j2
@Component(value = "PRIORITY_POINT_RULE")
public class PriorityRuleInterceptor extends AbstractGradeRuleAdapter {

    private static final String RULE_KEY = "priority";
    private List<PriorityRulesParams> priorityRulesParams;

    @Override
    public Mono<GradeRuleInterceptorRegistration> prepare(GradeRuleInterceptorRegistration gradeRuleInterceptorRegistration) {
        this.priorityRulesParams = super.objectMapper
                .convertValue(gradeRuleInterceptorRegistration.getRule().getParams(),
                        new TypeReference<>() {
                        });
        return Mono.just(gradeRuleInterceptorRegistration);
    }

    @Override
    public Mono<PointResult> scoring(JsonNode ticket) {
        int point = 0;
        Integer priorityId = super.getIntValueId(ticket.get("priority"));
        String priorityName = super.getStringValueName(ticket.get("priority"));
        if (!ObjectUtils.isEmpty(priorityId)) {
            point = priorityRulesParams.parallelStream().filter(item -> item.selected && item.getPriorityId().equals(priorityId))
                    .mapToInt(PriorityRulesParams::getPoints).sum();
        }
        return Mono.just(PointResult.withDefault().point(point)
                .detail(PointResult.Detail.with(point, Map.of("priorityName", priorityName), RULE_KEY)));
    }


    @Data
    private static class PriorityRulesParams {
        private Integer priorityId;
        private Integer points;
        private boolean selected;
    }

}
